import csv
import random
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

from util.util_image import draw_img_xyz, draw_img
from util.util_csv import read_csv_to_numpy_array
from util.util_ris_pattern_2 import phase_2_pattern_thph, eps


# 画3条折线图
def plot_linechart_compare(th, th_measurement, pattern_python, pattern_hfss, pattern_measurement):
    # 设置图表大小
    plt.figure(figsize=(10, 6))
    # 绘制三条折线
    # x轴是 'Theta' 列，y轴分别是 'python', 'HFSS', 'real' 列
    # plt.plot(df['Theta'], df['python'], marker='o', linestyle='-', label='Python')
    # plt.plot(df['Theta'], df['HFSS'], marker='s', linestyle='--', label='HFSS')
    # plt.plot(df['Theta'], df['real'], marker='^', linestyle='-.', label='Real')
    plt.plot(th, pattern_python, linestyle='--', color='black', label='Calculation')
    plt.plot(th, pattern_hfss, linestyle='-.', color='green', label='Simulation')
    plt.plot(th_measurement, pattern_measurement, linestyle='-', color='red', label='Measurement')
    # 添加图表标题和轴标签
    # plt.title('Comparison of Values across Theta')
    plt.xlabel('Theta')
    plt.ylabel('Normalized pattern')
    # 显示图例
    plt.legend()
    # 添加网格线以便阅读
    plt.grid(True, linestyle=':', alpha=0.7)
    # 自动调整布局以防止标签被遮挡
    plt.tight_layout()
    # 显示图表
    plt.show()


# ============================================ 业务代码 -- 方向图 python ================================================
# 获取截面pattern, th, ph -- Python模拟
def get_pattern_python(path_csv_phaseBit):
    # 读取码阵
    phaseBit = read_csv_to_numpy_array(path_csv_phaseBit)
    # 计算方向图
    pattern, th, ph = phase_2_pattern_thph(phaseBit)
    pattern_dbw = 20 * np.log10(np.abs(pattern) / np.max(np.max(np.abs(pattern))) + eps)
    indices = (pattern_dbw < -40).nonzero()
    pattern_dbw[indices] = -40
    # th, ph 弧度转角度
    th_deg = np.rad2deg(th)
    ph_deg = np.rad2deg(ph)
    # 画2d验证
    # draw_img(pattern_dbw)
    return pattern_dbw, th, ph, th_deg, ph_deg


# 按theta获取截面pattern -- Python模拟
def get_pattern_python_by_th(path_csv_phaseBit, theta):
    pattern_dbw, th, ph, th_deg, ph_deg = get_pattern_python(path_csv_phaseBit)
    # 1. 找到th_deg值取整后等于theta的列号index_th
    # 取 th_deg 索引
    th_deg_first_row = th_deg[0, :]
    # 查找所有满足条件的索引
    matching_indices = np.where(th_deg_first_row == theta)[0]
    if matching_indices.size == 0:
        raise ValueError(f"在th_deg中未找到四舍五入后等于 {theta} 度的列。")
    elif matching_indices.size > 1:
        print(f"警告：找到多个四舍五入后等于 {theta} 度的列，索引为 {matching_indices}。将使用第一个。")
        index_th = matching_indices[0]
    else:
        index_th = matching_indices[0]

    # 2. 取出pattern中第index_th列
    pattern_column = pattern_dbw[:, index_th]

    # 3. 取出ph_deg中第index_th列
    ph_deg_column = ph_deg[:, index_th]

    return pattern_column, ph_deg_column, index_th


# 按phi获取截面pattern -- Python模拟
def get_pattern_python_by_ph(path_csv_phaseBit, phi):
    pattern_dbw, th, ph, th_deg, ph_deg = get_pattern_python(path_csv_phaseBit)
    # 1. 找到ph_deg值等于phi的行号index_ph
    # np.round 用于四舍五入，astype(int)转换为整数索引
    rounded_ph_deg_first_col = np.round(ph_deg[:, 0]).astype(int)
    # 查找所有满足条件的索引
    matching_indices = np.where(rounded_ph_deg_first_col == phi)[0]
    if matching_indices.size == 0:
        raise ValueError(f"在ph_deg中未找到四舍五入后等于 {phi} 度的行。")
    elif matching_indices.size > 1:
        print(f"警告：找到多个四舍五入后等于 {phi} 度的行，索引为 {matching_indices}。将使用第一个。")
        index_ph = matching_indices[0]
    else:
        index_ph = matching_indices[0]

    # 2. 取出pattern中第index_ph行
    pattern_row = pattern_dbw[index_ph, :]

    # 3. 取出th_deg中第index_ph行
    th_deg_row = th_deg[index_ph, :]

    # 4. 对于pattern_row, th_deg_row，从第1个数开始，隔3个数取1个, 使用NumPy的切片功能 [start:end:step]
    pattern_row_downsampled = pattern_row[::4]
    th_deg_row_downsampled = th_deg_row[::4]

    return pattern_row_downsampled, th_deg_row_downsampled, index_ph


# ============================================ 业务代码 -- 方向图 HFSS ================================================
# 获取截面pattern -- HFSS
def get_pattern_hfss(path_hfss2d, row_name_th, row_name_pattern):
    # 1. 读取CSV文件, 使用 pandas.read_csv 读取，因为它能很好地处理带空格的列名
    df = pd.read_csv(path_hfss2d)
    # 2. 提取指定列的数据
    th_deg = df[row_name_th].to_numpy()
    pattern_hfss = df[row_name_pattern].to_numpy()
    #
    return th_deg, pattern_hfss


# ============================================ 业务代码 -- 方向图 实测 ================================================
# 读取实测3d的.csv
def read_from_csv(path_csv):
    x_coords = []
    y_coords = []
    z_values = []
    with open(path_csv, 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            x_coords.append(float(row['X']))
            y_coords.append(float(row['Y']))
            z_values.append(float(row['Z']))
    x_coords = np.unique(np.array(x_coords))
    y_coords = np.unique(np.array(y_coords))
    z_values = np.array(z_values).reshape((len(x_coords), len(y_coords)))
    return x_coords, y_coords, z_values


# 寻找最大值和次大值
def find_max_and_second_max_coords(pattern_matrix):
    if pattern_matrix.size < 2:
        raise ValueError("输入矩阵至少需要包含2个元素才能找到最大值和次大值。")
    # 获取矩阵的形状
    rows, cols = pattern_matrix.shape
    # 1. 将二维索引展平为一维索引
    # np.argmax 返回最大值的展平索引
    flat_index_max = np.argmax(pattern_matrix)
    # 2. 将展平索引转换回二维坐标 (row, col)
    max_row, max_col = divmod(flat_index_max, cols)
    # 3. 为了找到次大值，我们需要考虑所有元素
    flat_indices = np.argpartition(pattern_matrix.ravel(), -2)
    # 获取最大值和次大值的展平索引
    flat_index_second_max = flat_indices[-2]
    # 4. 将次大值的展平索引转换回二维坐标
    second_max_row, second_max_col = divmod(flat_index_second_max, cols)
    return (max_row, max_col), (second_max_row, second_max_col)


# 获取截面pattern -- 实测 -- 单波束 (有魔法值, 希望和双波束合并)
def get_pattern_measurement_beam1(path_measure3d):
    # 读取结果
    th1_coords, th2_coords, pattern_matrix = read_from_csv(path_measure3d)
    # pattern归一化
    # pattern_matrix = pattern_matrix - np.max(pattern_matrix)
    pattern_matrix = np.power(10, (pattern_matrix / 20))
    pattern_matrix = pattern_matrix / np.max(pattern_matrix)
    pattern_matrix = 20 * np.log10(pattern_matrix)
    indices = (pattern_matrix < -40).nonzero()
    pattern_matrix[indices] = -40
    # fixme: 此处强取 th = 0 的列 (有魔法值, 希望和双波束合并)
    th_deg = th1_coords
    pattern_dbw = pattern_matrix[:, 67]
    return th_deg, pattern_dbw


# 获取截面pattern -- 实测 -- 双波束 (有魔法值, 希望和双波束合并)
def get_pattern_measurement_beam2(path_measure3d):
    # 读取结果
    th1_coords, th2_coords, pattern_matrix = read_from_csv(path_measure3d)
    # pattern归一化
    # pattern_matrix = pattern_matrix - np.max(pattern_matrix)
    pattern_matrix = np.power(10, (pattern_matrix / 20))
    pattern_matrix = pattern_matrix / np.max(pattern_matrix)
    pattern_matrix = 20 * np.log10(pattern_matrix)
    indices = (pattern_matrix < -40).nonzero()
    pattern_matrix[indices] = -40
    # fixme: 此处强取 (53,50) (82,80) 的连线列 (有魔法值, 希望和双波束合并)
    # th_deg = th1_coords
    th_deg = [-90.0, -89.0, -88.0]
    pattern_dbw = [-40.0, -40.0, -40.0]
    for i in range(3, 135):
        x = i
        if x == 53:
            y = 50
        elif x == 82:
            y = 80
        else:
            y = i - 3
        sin_th1 = np.sin(np.deg2rad(th2_coords[x]))
        sin_th2 = np.sin(np.deg2rad(th1_coords[y]))
        sin_th1 = sin_th1 ** 2
        sin_th2 = sin_th2 ** 2
        angle = np.arcsin((sin_th1 + sin_th2) ** (1/2))
        th_deg.append(np.rad2deg(angle))
        pattern_dbw.append(pattern_matrix[x, y])
    pattern_dbw = np.array(pattern_dbw)
    th_deg_1 = np.array(th_deg[24:69])
    th_deg_1 = -th_deg_1
    th_deg_2 = np.array(th_deg[69:114])
    th_deg = np.concatenate((th_deg_1, th_deg_2), axis=0)
    return th_deg, pattern_dbw[24: 114]



# ========================================= 主函数: python & HFSS & 实测 比较图 ==========================================
# 比较图 -- 横轴为 theta
def main_theta(python_path, python_phi_1, python_phi_2,
               hfss_path, hfss_row_name_th, hfss_row_name_pattern,
               measurement_path, beam_num):
    # 1.获取pattern, th
    # 1.1 获取pattern, th -- python
    pattern_python_1, th_deg_python_1, index_ph_python_1 = get_pattern_python_by_ph(python_path, python_phi_1)
    pattern_python_2, th_deg_python_2, index_ph_python_2 = get_pattern_python_by_ph(python_path, python_phi_2)
    # 翻转 pattern_python_1
    pattern_python_1_flipped = np.flip(pattern_python_1)
    th_deg_python_1_flipped = np.flip(-th_deg_python_1)
    # 连接翻转后的 pattern_python_1 和 pattern_python_2
    pattern_python = np.concatenate((pattern_python_1_flipped, pattern_python_2[1:]))
    th_deg_python = np.concatenate((th_deg_python_1_flipped, th_deg_python_2[1:]))

    # 1.2 获取pattern, th -- HFSS
    th_deg_hfss, pattern_hfss = get_pattern_hfss(hfss_path, hfss_row_name_th, hfss_row_name_pattern)

    # 1.3 获取pattern, th -- 实测
    if beam_num == 2:
        th_deg_measurement, pattern_measurement = get_pattern_measurement_beam2(measurement_path)
    else:
        th_deg_measurement, pattern_measurement = get_pattern_measurement_beam1(measurement_path)

    # 2.画图
    plot_linechart_compare(th_deg_hfss, th_deg_measurement, pattern_python, pattern_hfss, pattern_measurement)




# 比较图 -- 横轴为 phi
def main_phi(python_path, python_theta, hfss_path, measurement_path):
    pattern_col, ph_deg_col, index_th = get_pattern_python_by_th(python_path, 20)


if __name__ == "__main__":
    main_theta(
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/theta(0,60)-phi(0,0)-20250816/phaseBit_AGA_(0,0).csv",
        0, 180,
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/32x32-beam1(0,0)-rE_Plot_2d_theta(20dbnor).csv",
        'Theta [deg]',
        'dB20normalize(rETotal) []',
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/1-3D.csv",
        1
    )
    main_theta(
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/beam2-(20,45)-(20,225)/phaseBit_AGA_(((20,45),(20,225))).csv",
        45, 225,
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/32x32-beam2(20,45)(20,225)-rE_Plot_2d_theta(db20nor).csv",
        'Theta [deg]',
        'dB20normalize(rETotal) []',
        "../../files/dissertation/chapter_2-sim-AGA/32x32-d9.3mm-FD0.905/10-3D.csv",
        2
    )

